package lingscale.cc01.core

import chisel3.UInt
import chisel3.util.BitPat

object Instructions {
                       //10987654321098765432109876543210
                       //3     22   21   11 11           
                       //1     54   09   54 21   76     0
  // RV32I Base Integer Instruction Set, Version 2.0  47 + 1
  def LUI     = BitPat("b?????????????????????????0110111")   // lui   rd, imm[31:12]    load upper immediate           | imm[31:12] | rd | opcode |
  def AUIPC   = BitPat("b?????????????????????????0010111")   // auipc rd, imm[31:12]    add upper immediate to pc
  def JAL     = BitPat("b?????????????????????????1101111")   // jal  rd, imm[20:1]        jump and link                | imm[20] | imm[10:1] | imm[11] | imm[19:12] | rd | opcode |
  def JALR    = BitPat("b?????????????????000?????1100111")   // jalr rd, rs1, imm[11:0]   jump and link register      | imm[11:0] | rs1 | funct3 | rd | opcode |
  def BEQ     = BitPat("b?????????????????000?????1100011")   // beq  rs1, rs2, imm[12:1]   branch equal                | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
  def BNE     = BitPat("b?????????????????001?????1100011")   // bne  rs1, rs2, imm[12:1]   branch not equal
  def BLT     = BitPat("b?????????????????100?????1100011")   // blt  rs1, rs2, imm[12:1]   branch if rs1 is less than rs2, signed
  def BGE     = BitPat("b?????????????????101?????1100011")   // bge  rs1, rs2, imm[12:1]   branch if rs1 is greater or equal to rs2, signed
  def BLTU    = BitPat("b?????????????????110?????1100011")   // bltu rs1, rs2, imm[12:1]   branch if rs1 is less than rs2, unsigned
  def BGEU    = BitPat("b?????????????????111?????1100011")   // bgeu rs1, rs2, imm[12:1]   branch if rs1 is greater or equal to rs2, unsigned
  def LB      = BitPat("b?????????????????000?????0000011")   // lb  rd, offset[11:0](rs1)        | imm[11:0] | rs1 | funct3 | rd | opcode |
  def LH      = BitPat("b?????????????????001?????0000011")   // lh  rd, offset[11:0](rs1)
  def LW      = BitPat("b?????????????????010?????0000011")   // lw  rd, offset[11:0](rs1)
  def LBU     = BitPat("b?????????????????100?????0000011")   // lbu rd, offset[11:0](rs1)
  def LHU     = BitPat("b?????????????????101?????0000011")   // lhu rd, offset[11:0](rs1)
  def SB      = BitPat("b?????????????????000?????0100011")   // sb  rs2, offset[11:0](rs1)        | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode |
  def SH      = BitPat("b?????????????????001?????0100011")   // sh  rs2, offset[11:0](rs1)
  def SW      = BitPat("b?????????????????010?????0100011")   // sw  rs2, offset[11:0](rs1)
  def ADDI    = BitPat("b?????????????????000?????0010011")   // addi   rd, rs1, imm[11:0]    | imm[11:0] | rs1 | funct3 | rd | opcode |
  def SLTI    = BitPat("b?????????????????010?????0010011")   // slti   rd, rs1, imm[11:0]
  def SLTIU   = BitPat("b?????????????????011?????0010011")   // sltiu  rd, rs1, imm[11:0]
  def XORI    = BitPat("b?????????????????100?????0010011")   // xori   rd, rs1, imm[11:0]
  def ORI     = BitPat("b?????????????????110?????0010011")   // ori    rd, rs1, imm[11:0]
  def ANDI    = BitPat("b?????????????????111?????0010011")   // andi   rd, rs1, imm[11:0]
  def SLLI    = BitPat("b0000000??????????001?????0010011")   // slli   rd, rs1, shamt[4:0]   | imm[11:5] | imm[4:0] | rs1 | funct3 | rd | opcode |
  def SRLI    = BitPat("b0000000??????????101?????0010011")   // srli   rd, rs1, shamt[4:0]
  def SRAI    = BitPat("b0100000??????????101?????0010011")   // srai   rd, rs1, shamt[4:0]
  def ADD     = BitPat("b0000000??????????000?????0110011")   // add  rd, rs1, rs2             | funct7 | rs2 | rs1 | funct3 | rd | opcode |
  def SUB     = BitPat("b0100000??????????000?????0110011")   // sub  rd, rs1, rs2
  def SLL     = BitPat("b0000000??????????001?????0110011")   // sll  rd, rs1, rs2[4:0]
  def SLT     = BitPat("b0000000??????????010?????0110011")   // slt  rd, rs1, rs2
  def SLTU    = BitPat("b0000000??????????011?????0110011")   // sltu rd, rs1, rs2
  def XOR     = BitPat("b0000000??????????100?????0110011")   // xor  rd, rs1, rs2
  def SRL     = BitPat("b0000000??????????101?????0110011")   // srl  rd, rs1, rs2[4:0]
  def SRA     = BitPat("b0100000??????????101?????0110011")   // sra  rd, rs1, rs2[4:0]
  def OR      = BitPat("b0000000??????????110?????0110011")   // or   rd, rs1, rs2
  def AND     = BitPat("b0000000??????????111?????0110011")   // and  rd, rs1, rs2
  def FENCE   = BitPat("b0000????????00000000000000001111")   // fence              |           | rs1 | funct3 | rd | opcode |
  def FENCEI  = BitPat("b00000000000000000001000000001111")   // fence.i            | imm[11:0] | rs1 | funct3 | rd | opcode |
  def ECALL   = BitPat("b00000000000000000000000001110011")   // ecall      environment call        | funct12 | rs1 | funct3 | rd | opcode |
  def EBREAK  = BitPat("b00000000000100000000000001110011")   // ebreak     environment breakpoint
  def CSRRW   = BitPat("b?????????????????001?????1110011")   // csrrw  rd, csr, rs1         | csr | rs1 | funct3 | rd | opcode |
  def CSRRS   = BitPat("b?????????????????010?????1110011")   // csrrs  rd, csr, rs1
  def CSRRC   = BitPat("b?????????????????011?????1110011")   // csrrc  rd, csr, rs1
  def CSRRWI  = BitPat("b?????????????????101?????1110011")   // csrrwi rd, csr, imm[4:0]    | csr | uimm| funct3 | rd | opcode |
  def CSRRSI  = BitPat("b?????????????????110?????1110011")   // csrrwi rd, csr, imm[4:0]
  def CSRRCI  = BitPat("b?????????????????111?????1110011")   // csrrwi rd, csr, imm[4:0]

  def NOP     = BitPat.bitPatToUInt(BitPat("b00000000000000000000000000010011"))   // ADDI x0, x0, 0

  // RISC-V Privileged Architectures V1.10
  // Machine-Mode Privileged Instructions  6?
//def ECALL   = BitPat("b00000000000000000000000001110011")   // belongs to RV32I?             | funct12 | rs1 | funct3 | rd | opcode |
//def EBREAK  = BitPat("b00000000000100000000000001110011")   // belongs to RV32I?
  def URET    = BitPat("b00000000001000000000000001110011")   // uret
  def SRET    = BitPat("b00010000001000000000000001110011")   // sret
  def MRET    = BitPat("b00110000001000000000000001110011")   // mret
  def WFI     = BitPat("b00010000010100000000000001110011")   // wfi      wait for interrupt
}
